﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace neside3
{
    public static partial class IDE
    {
        public enum DocOutState
        {
            None,
            Change,
            Miss
        }
        public class DocumentInIDE
        {
            public DocumentInIDE(ext.IDocumentInEditor docInEditor)
            {
                this.docInEditor = docInEditor;
                this.docPage = new TabItem();
                this.docPage.Tag = this;
                func_edit.TabHead head = new func_edit.TabHead(filename);
                this.docPage.Header = head;
                head.onBtnExitDown += this.Close;

                var page = new func_edit.TabPage(filename);
                page.SetContent(this.docInEditor.ui_editor);
                this.docPage.Content = page; ;
                this.docInEditor.OnChangeInEditor += (d) => SetInChange();
                //this.docInEditor.OnSaveInEditor += (d) => SaveIn();
                page.onIgnore += this.ClearOutState;
                page.onClose += this.Close;
                page.onReload += this.Reload;
            }
            public string filename
            {
                get
                {
                    return docInEditor.filename;
                }
            }
            public ext.IDocumentInEditor docInEditor
            {
                get;
                private set;
            }
            public TabItem docPage
            {
                get;
                private set;
            }
            public UIElement GetUIInfo()
            {
                return docInEditor?.ui_fileinfo;
            }
            public bool inedit
            {
                get;
                private set;
            }
            public DocOutState outstate
            {
                get;
                private set;
            }
            //关闭 内部或外部
            public void Close()
            {
                if (this.outstate != DocOutState.None)
                {
                    MessageBox.Show("此时不能保存，先处理外部问题");
                    return;
                }
                if (this.inedit)
                {
                    var s = MessageBox.Show("有编辑，是否要放弃编辑 YES:close without save    NO:do not close", "", MessageBoxButton.YesNo);
                    if (s == MessageBoxResult.Yes)
                    {
                        IDE.Documents.CloseFile(this);
                    }
                    return;
                }
                IDE.Documents.CloseFile(this);
            }
            public void Reload()
            {
                this.docInEditor.Load();
                this.inedit = false;
                var head = this.docPage.Header as func_edit.TabHead;
                head.SetEditState(false);
                ClearOutState();
            }
            //内部改变
            //DateTime? savetime = null;
            int savetime = 0;
            public void Save()
            {
                if (this.outstate != DocOutState.None)
                {
                    MessageBox.Show("此时不能保存，先处理外部问题");
                    return;
                }
                if (this.inedit)
                {
                    this.docInEditor.Save();
                    savetime = 1;

                    this.inedit = false;
                    var head = this.docPage.Header as func_edit.TabHead;
                    head.SetEditState(false);

                }
            }
            void SetInChange()
            {
                inedit = true;
                var head = this.docPage.Header as func_edit.TabHead;
                head.SetEditState(true);
            }
            public void SetOutChange(bool miss)
            {
                //监视filter的锅
                if (savetime >0 )
                {
                    if (!miss)
                        savetime--;

                    return;
                }
                outstate = miss ? DocOutState.Miss : DocOutState.Change;
                this.docPage.Dispatcher.Invoke(() =>
                {
                    var head = this.docPage.Header as func_edit.TabHead;
                    if (this.inedit)
                        head.SetError();
                    else
                        head.SetWarn();
                    var page = this.docPage.Content as func_edit.TabPage;
                    if (miss)
                        page.SetOutMiss();
                    else
                        page.SetOutChange();
                });

            }
            public void ClearOutState()
            {
                outstate = DocOutState.None;
                var head = this.docPage.Header as func_edit.TabHead;
                head.SetNormal();
                var page = this.docPage.Content as func_edit.TabPage;
                page.SetNormal();
            }
        }

        public static class Documents
        {
            static TabControl docContainer;
            public static void Init(TabControl _docContainer)
            {
                Documents.docContainer = _docContainer;
            }
            //public static event Action<string, string> onFileChange;
            public static void OutChange(string folder, string filename, bool miss)
            {

                //onFileChange?.Invoke(folder, filename);
                if (allfiles.ContainsKey(filename))
                {
                    allfiles[filename].SetOutChange(miss);
                }
            }

            static Dictionary<string, DocumentInIDE> allfiles = new Dictionary<string, DocumentInIDE>();
            public static DocumentInIDE OpenFile(string filename)
            {
                if (allfiles.ContainsKey(filename))
                {
                    allfiles[filename].docPage.Focus();
                    return allfiles[filename];
                }
                var extname = System.IO.Path.GetExtension(filename).ToLower();
                if (mapext2editor.TryGetValue(extname, out int id))
                {
                    var doc = IDE.plugin_editor[id].OpenFile(logger, filename);
                    allfiles[filename] = new DocumentInIDE(doc);
                    docContainer.Items.Add(allfiles[filename].docPage);

                    docContainer.UpdateLayout();
                    allfiles[filename].docPage.Focus();
                    return allfiles[filename];
                }
                return null;
            }
            public static void CloseFile(DocumentInIDE doc)
            {
                docContainer.Items.Remove(doc.docPage);
                allfiles.Remove(doc.filename);
                var extname = System.IO.Path.GetExtension(doc.filename).ToLower();
                if (mapext2editor.TryGetValue(extname, out int id))
                {
                    IDE.plugin_editor[id].CloseFile(doc.docInEditor);
                }
            }

            public static void SaveCurrentFile()
            {
                DocumentInIDE doc = (docContainer.SelectedItem as TabItem)?.Tag as DocumentInIDE;
                if (doc != null)
                    doc.Save();
            }
            public static void SaveAllFile()
            {
                int outerr = 0;
                foreach (var f in allfiles)
                {
                    if (f.Value.outstate != DocOutState.None)
                    {
                        outerr++;
                        continue;
                    }
                    f.Value.Save();
                }
                if (outerr > 0)
                {
                    MessageBox.Show("发现" + outerr + "个文件外部修改，不能保存，请检查");
                }
            }
            public static void CloseAllFile()
            {
                List<DocumentInIDE> readyToClose = new List<DocumentInIDE>();
                int outerr = 0;
                foreach (var f in allfiles)
                {
                    if (f.Value.outstate != DocOutState.None || f.Value.inedit)
                    {
                        outerr++;
                        continue;
                    }
                    readyToClose.Add(f.Value);
                }
                foreach (var d in readyToClose)
                {
                    d.Close();
                }
                if (outerr > 0)
                {
                    MessageBox.Show("发现" + outerr + "个文件有修改，不能保存，请检查");
                }
            }
        }
    }
}
